#include <iostream>
#include "card_table.h"
using namespace dymy;
using namespace dymy::card;
using namespace std;

std::ostream &operator<<(std::ostream &os, const std::vector<card_t> &cards);
std::ostream &operator<<(std::ostream &os, const std::vector<std::vector<card_t>> &cards);
std::ostream &operator<<(std::ostream &os, const multiple_card_t &cards);
ostream &operator<<(ostream &os, const table::Person &p);
ostream &operator<<(ostream &os, const AllCards_t &cards);
std::vector<card_num_t> split(std::string, std::string);
multiple_card_t custom_cards(string cards);

int main(int, char **)
{
    std::cout << "generator_test:" << std::endl;
    constexpr size_t aN = 54; //一副牌54张
    constexpr size_t pN = 3;  //一共三个玩家
    constexpr size_t eN = 17; //每个玩家17张牌
    constexpr size_t hN = 3;  //三张底牌
    using table_manager = table::TableController<aN, pN, eN, hN>;
    using generator = typename table_manager::CardGenerator_;
    using table = typename table_manager::CardTable_;
    shared_ptr<generator::AllCards> all_cards = make_shared<generator::AllCards>(card::MakeAllCards());
    //创建卡牌生成器
    shared_ptr<generator> g = make_shared<generator>(std::move(all_cards));
    //创建一个id为1的牌桌
    table t(1);
    table *tp = &t;
    //创建一个牌桌管理器
    table_manager tm(g);

    //添加3个玩家
    tm.add_person(tp, 0, 1, "user1");
    tm.add_person(tp, 1, 2, "user2");
    tm.add_person(tp, 2, 3, "user3");

    //3个玩家准备
    tm.prepared(tp, 0, 1, true);
    tm.prepared(tp, 1, 2, true);
    tm.prepared(tp, 2, 3, true);

    //开始游戏
    if (tm.start(tp) != 1)
    {
        cout << "开始游戏失败" << endl;
        return 0;
    }

    cout << "开始游戏成功" << endl;

    //让一个玩家抢地主
    auto &u = tp->find_user(tp->get_current_table_landlord_index());
    if (tm.rob_landlord(tp, tp->get_current_table_landlord_index(), u->user_id, true) == 1)
    {
        cout << "位置" << tp->get_current_table_landlord_index() << "的玩家抢地主成功" << endl;
    }

    while (tp->get_step() == STEP_PLAYING)
    {
        for (size_t i = 0; i < tp->get_persons().size(); i++)
        {
            auto &p = *tp->find_user(i);
            cout << p;
            if (tp->get_play_cards_index() == i)
            {
                cout << '*';
            }
            cout << endl;
            /* code */
        }
        string s;
        std::getline(cin, s);
        auto t = split(s, " ");
        int result = tm.play_cards(tp, tp->get_play_cards_index(), tp->find_user(tp->get_play_cards_index())->user_id, t);
        switch (result)
        {
        case 1:
            cout << "出牌成功" << endl;
            break;
        default:
            cout << "出牌错误:" << result << endl;
            break;
        }
    }

    cout << "游戏结束" << endl;
    tm.remove_person(tp, 0, 1);
    tm.remove_person(tp, 1, 2);
    tm.remove_person(tp, 2, 3);
}

std::vector<card_t> split(std::string ss, std::string s)
{
    std::vector<card_t> cards;
    const int s_l = s.length();
    int start_index = 0;

    int end_index;
    while ((end_index = ss.find(s, start_index)) >= 0)
    {
        std::string str = ss.substr(start_index, end_index - start_index);
        if (str.length() > 0)
        {
            cards.push_back(static_cast<card_t>(std::stoi(str)));
        }
        start_index = end_index + s_l;
    }
    if (start_index < ss.length())
    {
        std::string str = ss.substr(start_index, end_index - start_index);
        if (str.length() > 0)
        {
            cards.push_back(static_cast<card_t>(std::stoi(str)));
        }
    }
    return cards;
}

multiple_card_t custom_cards(string cards)
{
    auto t = split(cards, " ");
    multiple_card_t ret(t.cbegin(), t.cend());
    return ret;
}

std::ostream &operator<<(std::ostream &os, const dymy::card_t &c)
{
    return os << static_cast<int>(c) << "(" << static_cast<int>(dymy::card::decode_card_num(c)) << ")";
}

std::ostream &operator<<(std::ostream &os, const std::vector<card_t> &cards)
{
    for (auto begin = cards.cbegin(); begin != cards.cend(); ++begin)
    {
        os << *begin << ' ';
    }
    return os;
}

std::ostream &operator<<(std::ostream &os, const std::vector<std::vector<card_t>> &cards)
{
    for (auto begin = cards.cbegin(); begin != cards.cend(); ++begin)
    {
        os << *begin;
    }
    return os;
}

std::ostream &operator<<(std::ostream &os, const multiple_card_t &cards)
{
    for (auto begin = cards.cbegin(); begin != cards.cend(); ++begin)
    {
        os << *begin << ' ';
    }
    return os;
}

ostream &operator<<(ostream &os, const table::Person &p)
{
    os << p.user_name << ' ' << (p.role == table::Role::ROLE_LANDLORD ? "地主" : "农民") << '[' << p.cards << ']';
    return os;
}

ostream &operator<<(ostream &os, const AllCards_t &cards)
{
    for (auto begin = cards.cbegin(); begin != cards.cend(); ++begin)
    {
        os << *begin << ' ';
    }
    return os;
}